package com.junxian.springboot03.juc.threadPool;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;


/**
 * <p>线程池map(每个业务单独对应一个线程池)</p>
 */
public class ThreadPoolMapUtil {

	protected static Map<String,ThreadPoolExecutor> threadPoolMap = new HashMap<String, ThreadPoolExecutor>();
	private static Object lock = new Object();

	/**
	 * 创建线程池
	 * @return
	 */
	public static ThreadPoolExecutor createThreadPool(String name, int coreThreads ,int maxThreads ,int queues,String bizCode){

		synchronized (lock) {
			if(threadPoolMap.containsKey(bizCode)){
				return threadPoolMap.get(bizCode);
			}

			//不存在 则创建该业务线程池
			ThreadPoolExecutor threadPoolExecutor =new ThreadPoolExecutor(coreThreads, maxThreads, 0, TimeUnit.MILLISECONDS,
					queues == 0 ? new SynchronousQueue<Runnable>() :
							(queues < 0 ? new LinkedBlockingQueue<Runnable>()
									: new LinkedBlockingQueue<Runnable>(queues))
//					, new NamedThreadFactory(name, true), new AbortPolicyWithReportDetail(name)
			);

			ThreadPoolMapUtil.threadPoolMap.put(bizCode, threadPoolExecutor);
			return threadPoolExecutor;
		}
	}

	/**
	 * 初始化线程池参数
	 * @return
	 */
//	public static BatchThreadParams initThreadPoolParams(int detailSize,int maxConcur,int maxDealSizeEachTime){
//		BatchThreadParams params = new BatchThreadParams();
//		params.setTotalSize(detailSize);
//		params.setMaxDealSizeEachTime(maxDealSizeEachTime);
//
//		int dealCount = detailSize / maxDealSizeEachTime;
//		int restDealCount = detailSize % maxDealSizeEachTime;
//		int finalDealCount = dealCount + (restDealCount > 0 ? 1 : 0);
//		int finalMaxConcur = finalDealCount > maxConcur ? maxConcur : finalDealCount;
//		params.setMaxConcurUse(finalMaxConcur);
//		return params;
//	}

	/**
	 * 初始化第 i 条交易线程参数。过程：
	 * 交易总数 除以 每页数量(m) 得到 商：页数(c)，余数：p,(0<=p<m)
	 * 页数 除以 线程数量(n) 得到 商：每个线程第一次分配的页数(d)，余数：q,(0<=q<n)
	 * 第 i 个线程处理 (d+1)*m 笔交易，(1<=i<=q<n)
	 * 第 j 个线程处理 d*m 笔交易，(0<=q<j<n)
	 * 第 n 个线程处理 d*m+p 笔交易，(q<j<n)
	 * @param i 线程序号
	 * @param params 线程池参数
	 * @return
	 */
//	public static BatchThreadDealParams initDealThreadPoolParams(int i,BatchThreadParams params){
//		int totalSize = params.getTotalSize();
//		int maxDealSizeEachTime = params.getMaxDealSizeEachTime();
//		int maxConcurUse = params.getMaxConcurUse();
//
//		int dealCount = totalSize / maxDealSizeEachTime;//dealCount 或者 dealCount+1 是所有线程共需要循环次数，也是分页总数
//		int restDealSize = totalSize % maxDealSizeEachTime;
//		int dealCountEachThread = dealCount / maxConcurUse;//dealCountEachThread 或者 dealCountEachThread+1 是单个线程需要循环次数
//		int restDealCount2 = dealCount % maxConcurUse;
//
//		BatchThreadDealParams dealParams = new BatchThreadDealParams();
//		if (i == maxConcurUse) {
//			int finalDealCount = dealCountEachThread + (restDealSize > 0 ? 1 : 0);
//			dealParams.setDealCount(finalDealCount);
//			dealParams.setTotalSize(dealCountEachThread * maxDealSizeEachTime + restDealSize);
//			int pageNumVisited = (totalSize - dealParams.getTotalSize()) / maxDealSizeEachTime;
//			dealParams.setPageNum(pageNumVisited + 1);
//		} else {
//			int finalDealCount = dealCountEachThread + (i <= restDealCount2 ? 1 : 0);
//			dealParams.setDealCount(finalDealCount);
//			dealParams.setTotalSize(finalDealCount * maxDealSizeEachTime);
//
//			// 计算前 i-1 个线程共需要访问多少页
//			int pageNumVisited1 = dealCountEachThread * (i - 1); // 前 i-1 个线程第一次分配到的页数和
//			int pageNumVisited2 = i <= restDealCount2 ? i - 1 : restDealCount2;// 前 i-1 个线程第二次分配到的页数和
//
//			dealParams.setPageNum(pageNumVisited1 + pageNumVisited2 + 1);
//		}
//		dealParams.setDealSize(maxDealSizeEachTime);
//		return dealParams;
//	}

	/**
	 * 初始化线程池
	 * @param name 线程名
	 * @param coreThread 核心线程数
	 * @param maxThread 最大线程数
	 * @param queues 队列
	 * @param bizCode 业务编码
	 * @return
	 */
	public static ThreadPoolExecutor initThreadPool(String name, int coreThread ,int maxThread ,int queues,String bizCode){
		//check exist the thread pool
		if(ThreadPoolMapUtil.threadPoolMap.containsKey(bizCode)){
			return ThreadPoolMapUtil.threadPoolMap.get(bizCode);
		}

		//is not exist create a new one
		ThreadPoolExecutor threadPoolExecutor = ThreadPoolMapUtil.createThreadPool(name,coreThread,maxThread,queues,bizCode);
		return threadPoolExecutor;
	}
}
